package cn.yzgy.yzgyoa.ucenter.service.impl;

import cn.yzgy.yzgyoa.common.annotation.ApiDesc;
import cn.yzgy.yzgyoa.ucenter.dto.PermissionsFromHandlerDto;
import cn.yzgy.yzgyoa.ucenter.entity.SysPermission;
import cn.yzgy.yzgyoa.ucenter.entity.SysUser;
import cn.yzgy.yzgyoa.ucenter.mapper.SysPermissionMapper;
import cn.yzgy.yzgyoa.ucenter.service.ISysPermissionService;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;

import java.util.*;

/**
 * <p>
 * 权限表 服务实现类
 * </p>
 *
 * @author Yqsen
 * @since 2019-08-20
 */
@Slf4j
@Service
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements ISysPermissionService {

    private final ApplicationContext applicationContext;

    public SysPermissionServiceImpl(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public String flushAllPerms(){
        StringBuilder res = new StringBuilder();
        int updateCount = 0;
        // 获取系统内的全部权限
        List<PermissionsFromHandlerDto> perms = getPermissionsFromHandler();
        for (PermissionsFromHandlerDto perm : perms) {
            // 判断数据库是否存在此权限
            SysPermission permission = baseMapper.selectOne(new QueryWrapper<SysPermission>().lambda()
                    .eq(SysPermission::getPVal, perm.getPVal()));
            if (null != permission) {
                //数据库有
                if (!perm.getPName().equals(permission.getPName())) {
                    // 数据有变化
                    permission.setPName(perm.getPName()).setPUpdateTime(new Date());
                    updateById(permission);
                    res.append(String.format("更新条目：%s\n", permission.toString()));
                    updateCount++;
                }
            } else {
                SysPermission item = new SysPermission().setPVal(perm.getPVal())
                        .setPName(perm.getPName())
                        .setPUpdateTime(new Date())
                        .setPType(1)
                        .setPParent(0)
                        .setPCreateTime(new Date());
                save(item);
                updateCount++;
                res.append(String.format("新增条目：%s\n", item.toString()));
            }
        }
        if (updateCount == 0) {
            res.append("所有条目已最新");
        }
        return res.toString();
    }


    @Override
    public List<SysPermission> getPermissionsByUid(String uid) {
        return baseMapper.getPermissionsByUid(uid);
    }

    /**
     * 从Handler获取系统权限值及名称
     *
     * @return 修改的条数
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PermissionsFromHandlerDto> getPermissionsFromHandler() {
        List<PermissionsFromHandlerDto> handlerPermissions = new ArrayList<>();
        AbstractHandlerMethodMapping<RequestMappingInfo> requestMappingHandlerMapping =
                (AbstractHandlerMethodMapping<RequestMappingInfo>)applicationContext.getBean("requestMappingHandlerMapping");
        final Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
        int index = 1;
        for (RequestMappingInfo requestMappingInfo : handlerMethods.keySet()) {
            HandlerMethod handlerMethod = handlerMethods.get(requestMappingInfo);
            RequiresPermissions methodAnnotation = handlerMethod.getMethodAnnotation(RequiresPermissions.class);
            if (methodAnnotation != null) {
                ApiDesc apiDesc = handlerMethod.getMethodAnnotation(ApiDesc.class);
                String permissionVal = methodAnnotation.value()[0];
                String methodName = handlerMethod.getMethod().getName();
                String permissionName = apiDesc != null ? apiDesc.value() : "未定义";

                log.debug("方法名：{} 权限值：{} 操作名：{}",
                        methodName, permissionVal, permissionName);
                handlerPermissions.add(
                        new PermissionsFromHandlerDto()
                                .setIndex(index++)
                                .setHandlerName(methodName)
                                .setPName(permissionName)
                                .setPVal(permissionVal));
            }
        }
        return handlerPermissions;
    }

    /**
     * 更新或新增权限
     *
     * @param dto 权限DTO
     * @return 影响条数
     */
    @Override
    public int updateOrAddPermission(PermissionsFromHandlerDto dto) {
        final String pValColumnName = "p_val";
        int count = baseMapper.selectCount(new QueryWrapper<SysPermission>().eq(pValColumnName, dto.getPVal()));
        SysPermission sysPermission = new SysPermission();
        if (count > 0) {
            sysPermission
                    .setPVal(dto.getPVal())
                    .setPUpdateTime(new Date());
            // 更新操作
            return baseMapper.update(sysPermission, new UpdateWrapper<SysPermission>().eq(pValColumnName, dto.getPVal()));
        }
        // 新增操作
        return baseMapper.insert(sysPermission
                .setPName(dto.getPName())
                .setPVal(dto.getPVal())
                .setPUpdateTime(new Date())
                .setPCreateTime(new Date())
                .setPType(1)
                .setPParent(0));
    }

    @Override
    public List<Map<String, Object>> permissionsTree(String roleId) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        List<Map<String, Object>> permissionsList = baseMapper.getList(user.getId().toString());
        if(permissionsList.size()==0){
            permissionsList= baseMapper.getAllList();
        }
        List<Map<String, Object>> newspermsList = new ArrayList<>();
        Map<String,Object> bc = new HashMap<>();
        for(Map map:permissionsList){
            String[] params = map.get("id").toString().split(":");
            for(int i=0;i<params.length-1;i++){
                String key = "";
                String pidkey="";
                if(i==0){
                    key = params[0];
                }
                if(i==1){
                    key = params[0]+":"+params[1];
                    pidkey = params[0];
                }
                if(i==2){
                    key = params[0]+":"+params[1]+":"+params[2];
                    pidkey = params[0]+":"+params[1];
                }
                if(bc.containsKey(key)) {
                    continue;
                }
                bc.put(key,true);
                Map<String,Object> news = new HashMap<>();
                if("api".equals(key)){
                    news.put("title","第一级列表");
                }else{
                    news.put("title",map.get("title").toString().substring(0,map.get("title").toString().length()-2)+"相关");
                }
                if("".equals(pidkey)){
                    news.put("parentId","0");
                }else{
                    news.put("parentId",pidkey);
                }
                news.put("id",key);
                news.put("checkArr","0");
                newspermsList.add(news);
            }
        }
        permissionsList.addAll(newspermsList);
        //制造反选数据集
        List<Map<String, Object>> checkList = new LinkedList<>();
        Map<String, Object> checkMap = new HashMap<>();
        checkMap.put("type","0");
        checkMap.put("checked","1");
        checkList.add(checkMap);
        String checkArr = JSONArray.toJSONString(checkList);
        Map<String, Object> map;

        //遍历所有结果集进行数据创造并且赋予反选标志
        for (Map<String, Object> stringObjectMap : permissionsList) {
            map = stringObjectMap;
            if ("".equals(map.get("parentId")) || map.get("parentId") == null) {
                String[] params = map.get("id").toString().split(":");
                String pid = params[0] + ":" + params[1] + ":" + params[2];
                map.put("parentId", pid);
                //如果前端传入permissionId不为空，且是正常的权限集则遍历比对 添加选中属性
                if(roleId != null && !"".equals(roleId)){
                    List<SysPermission> perList = baseMapper.getPerList(roleId);
                    for (SysPermission sysPermission : perList) {
                        if (sysPermission.getPVal().equals(map.get("id"))) {
                            map.put("checkArr", checkArr);
                        }
                    }
                    if(map.get("checkArr") == null || "".equals(map.get("checkArr"))){
                        map.put("checkArr", "0");
                    }

                }
            }
        }
        return permissionsList;
    }

    @Override
    public Integer changeInfo(SysPermission perms) {
        return baseMapper.update(perms,new UpdateWrapper<SysPermission>().eq("p_val",perms.getPVal()));
    }

    @Override
    public List<SysPermission> getPermissionsList() {
        return baseMapper.getPermissionsList();
    }

    @Override
    public String getPid(String pVal) {
        return baseMapper.getPid(pVal);
    }

    @Override
    public String getPidToPname(String pName) {
        return baseMapper.getPidToPname(pName);
    }
}
